import os,re,time
from  Utils.backtick import *
from qt import *

class FileBasedPlayerScanner(QObject):
	def __init__(self):
		QObject.__init__(self)
		self.lastScan = {}
		self.unrecognized = []
		self.timer = QTimer()
		QObject.connect(self.timer,SIGNAL("timeout()"),self.doScan)
		self.timer.start(5000)
	
	def doScan(self):
		players = self.scanForPlayers()
		#
		# mount players that are in the current scan but not the previous one
		#
		for player in players.keys():
			if not self.lastScan.has_key(player):
				player.mount(players[player])
		#
		# unmount players that were in the previous scan but aren't in the current one
		#
		for player in self.lastScan.keys():
			if not players.has_key(player):
				player.unmount(self.lastScan[player])
		self.lastScan = players

	#
	# return true if this *could* be a player device - basically exclude cdrom and floppy devices
	#
	def possibleDevice(self,name):
		for n in ['floppy','cdrom']:
			if name.startswith(n):
				return False
		return True

	#
	# strategy - scan through ~ and /mnt looking for readable directories that correspond to
	# mounted emulated SCSI devices, then collect the vendor/model info and invoke an instance
	# of a corresponding class, if available
	#
	def scanForPlayers(self):
		#print "scanning for players"
		players = {}
		mountRoots = [os.path.expanduser('~'),'/mnt']
		mountDevices = backtick('mount')
		#print "devices:\n",mountDevices
		for mountRoot in mountRoots:
			if os.access(mountRoot,os.R_OK) and os.path.isdir(mountRoot):
				try:
					mountPoints = os.listdir(mountRoot)
					for mountPoint in mountPoints:
						if self.possibleDevice(mountPoint):
							mountPath = os.path.join(mountRoot,mountPoint)
							if os.access(mountPath,os.R_OK) and os.path.isdir(mountPath):
								#print "looking for",mountPath
								pattern = r"%s.*,dev=(.*?),"% mountPath
								#print "trying old pattern",pattern
								mountPattern = re.compile(pattern, re.MULTILINE)
								mo = mountPattern.search(mountDevices)
								if mo:
									devicePath = mo.group(1)
									scsiPath = os.readlink(str(devicePath))
									mountPattern = re.compile(r"scsi/host(\d)/bus(\d)/target(\d)/lun(\d)/part(\d)")
									mo = mountPattern.search(scsiPath)
								else:
									pattern = r"/dev/scsi/host(\d)/bus(\d)/target(\d)/lun(\d)/part(\d) on %s " % mountPath
									#print "trying new pattern",pattern
									mountPattern = re.compile(pattern, re.MULTILINE)
									mo = mountPattern.search(mountDevices)
								if mo:
									#print "found device"
									scsiPattern = re.compile(r"scsi%d Channel:\s*%02d Id:\s*%02d.*\s*Vendor:\s*(.*?)\s*Model:\s*(.*?)\s*Rev:\s*" % (int(mo.group(1)), int(mo.group(2)), int(mo.group(3))), re.MULTILINE)
									# ex. Vendor: Casio    Model: QV DigitalCamera Rev: 1000
									scsiLines = open("/proc/scsi/scsi").read()
									mo = scsiPattern.search(scsiLines, re.MULTILINE)
									if mo:
										vendor = mo.group(1)
										model = mo.group(2)
										className = '%s%sPlayer' % (vendor,model)
										#print className
										if not className in self.unrecognized:
											try:
												klass = eval(className)
												if klass.recognize(mountPath):
													player = klass(mountPath,vendor,model)
													#player = {'MountPath':mountPath,'Vendor':vendor,'Model':model}
													players[klass] = player
											except:
												#print "unrecognized device '%s'" % className
												self.unrecognized.append(className)
												pass
				except:
					pass
		return players
		
	def static_singleton():
		global _fileBasedPlayerScannerSingleton
		if _fileBasedPlayerScannerSingleton==None:
			_fileBasedPlayerScannerSingleton = FileBasedPlayerScanner()
		return _fileBasedPlayerScannerSingleton
		
	singleton = staticmethod(static_singleton)

_fileBasedPlayerScannerSingleton = FileBasedPlayerScanner()

class FileBasedPlayer(QObject):
	def __init__(self,mountPath,vendor,model):
		QObject.__init__(self)
		self.mountPath = mountPath
		self.vendor = vendor
		self.model = model

class RioCaliPlayer(FileBasedPlayer):
	def __init__(self,mountPath,vendor,model):
		FileBasedPlayer.__init__(self,mountPath,vendor,model)
	
	def iconFile(self):
		return "sourceriocali.png"

	def static_recognize(mountPath):
		return True	
	recognize = staticmethod(static_recognize)

	def static_mount(info):
		print "mounting Rio Cali"
	mount = staticmethod(static_mount)
	
	def static_unmount(info):
		print "unmounting Rio Cali"
	unmount = staticmethod(static_unmount)

class AppleiPodPlayer(FileBasedPlayer):
	def __init__(self,mountPath,vendor,model):
		FileBasedPlayer.__init__(self,mountPath,vendor,model)
	
	def iconFile(self):
		return "sourcepod.png"

	def static_recognize(mountPath):
		return True	
	recognize = staticmethod(static_recognize)

	def static_mount(player):
		#print "mounting AppleiPodPlayer",player.mountPath
		from PodLibrary import PodLibrary
		PodLibrary.mount(player.mountPath)
	mount = staticmethod(static_mount)
	
	def static_unmount(player):
		#print "unmounting AppleiPodPlayer",player.mountPath
		from PodLibrary import PodLibrary
		PodLibrary.unmount()
	unmount = staticmethod(static_unmount)

if __name__=='__main__':
	players = FileBasedPlayerScanner.singleton().scanForPlayers()
	for player in players.keys():
		print player,players[player]
